﻿using System;
using System.Collections.Generic;
using System.Linq;
using LinqToTwitter;
using Microsoft.SystemCenter.Orchestrator.Integration;
using SocialMediaIntegrationPack.Properties;

// Expression used to search direct messages
using searchFilter = System.Linq.Expressions.Expression<System.Func<LinqToTwitter.DirectMessage, bool>>;

namespace SocialMediaIntegrationPack
{
    [Activity("Get Direct Messages")]
    public class GetDirectMessagesAct : TwitterActivity
    {
        [ActivityInput("Messages Sent", Default = "Sent", Options = "Sent,Inbox")]
        public string QueryType
        {
            get { return queryType.ToString(); }
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException("Specify query type for direct messages search.");

                queryType = (value == "Sent") ? DirectMessageType.SentBy : DirectMessageType.SentTo;
            }
        }

        private DirectMessageType queryType;

        [ActivityInput("Attempts", Default = "1")]
        public string Attempts { get; set; }

        [ActivityOutput]
        public List<TweetData> Messages { get; set; }

        [ActivityOutput]
        public int MessagesFound { get; set; }

        public GetDirectMessagesAct()
        {            
        }

        [ActivityMethod]
        public void Execute()
        {
            try
            {
                var twitterContext = Authorize();

                var directMessages = new List<TweetData>();

                int attempts = 0;
                if (!(Int32.TryParse(Attempts, out attempts)) || attempts <= 0)
                {
                    throw new ArgumentException(Resources.INCORRECT_ATTEMPTS);
                }
                bool done = false;
                int _try = 1;
                do
                {
                    try
                    {
                        var directMessagesList = GetDirectMessages(twitterContext);
                        directMessagesList.ForEach(tweet =>
                            directMessages.Add(new TweetData(tweet.SenderScreenName, tweet.Text, tweet.CreatedAt))
                        );
                        done = true;
                    }
                    catch (TwitterQueryException ex)
                    {
                        if (ex.HttpError.Contains("502") || ex.HttpError.Contains("503") || ex.HttpError.Contains("504") || ex.HttpError.Contains("509"))
                        {
                            _try++;
                        }
                        else
                        {
                            throw;
                        }
                    }
                } while (!done && _try <= attempts);

                MessagesFound = directMessages.Count;
                Messages = directMessages;
                Response = string.Format(Resources.GetTweetAct_Run_Found_tweets, MessagesFound);
            }
            catch (TwitterQueryException twitterQueryException)
            {
                Response = twitterQueryException.HttpError ?? twitterQueryException.Message;
                if (string.IsNullOrEmpty(twitterQueryException.Response.Error))
                {
                    Response += " Twitter reported error: " + twitterQueryException.Response.Error;
                }
                if (Response.Contains(Resources.GetTweetAct_Run_404))
                {
                    // Suppress 404 error cause it occurs every time when no tweets were found
                    MessagesFound = 0;
                    return;
                }

                if (twitterQueryException.InnerException != null)
                {
                    Response = twitterQueryException.InnerException.Message;
                }

                throw new Exception(Response);
            }
            catch (Exception exception)
            {
                LogException(exception);
                throw;
            } 
        }

        /// <summary>
        /// Load Direct Messages from Twitter
        /// </summary>
        protected virtual List<DirectMessage> GetDirectMessages(TwitterContext twitterContext)
        {
            //
            // Common expression for loading of DM: by type
            //   By - sent by user
            //   To - recieved
            //
            searchFilter commonExpresion = dm => dm.Type == queryType;
            var additionalFilters = GetAdditionalFilters();

            var directMessagesList = (from tweet in twitterContext.DirectMessage
                                        .Where(commonExpresion)
                                        .WhereAll(additionalFilters)
                                      select tweet);

            var list = directMessagesList.ToList();
            AfterSearchComplete(directMessagesList);

            return list;
        }

        //
        // Additional filters for searching tweets
        //
        protected virtual IEnumerable<searchFilter> GetAdditionalFilters()
        {
            return new List<searchFilter> {dm => dm != null };
        }

        /// <summary>
        /// Additional actions on result set
        /// </summary>
        protected virtual void AfterSearchComplete(IQueryable<DirectMessage> result)
        {
        }
    }
}